﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;

namespace Bamboo.CodeCat
{
    /// <summary>
    /// 翻译模板，由一个文本文件和一个翻译类组成
    /// </summary>
    public class Template
    {
        /// <summary>
        /// 模板名称
        /// </summary>
        public string Name { get; }
        /// <summary>
        /// 模板的内容
        /// </summary>
        public string Content { get; }
        /// <summary>
        /// 模板对应的翻译类
        /// </summary>
        public Type Type { get; }

        /// <summary>
        /// 输出到文本文件时所使用的字符集
        /// 用户可自行指定
        /// 如果从文件加载模板，那么本属性的默认值为模板文件的字符集
        /// 如果从字符串加载模板，本属性的默认值为系统默认字符集
        /// </summary>
        public Encoding OutputEncoding { get; set; }

        public List<Macro> Macros { get; } = new List<Macro>();

        /// <summary>
        /// 从文件加载模板
        /// </summary>
        /// <param name="name"></param>
        /// <param name="filename"></param>
        /// <param name="encodingName"></param>
        /// <param name="templateType"></param>
        public Template(string name, string filename, Encoding encoding, Type templateType)
        {
            this.Name = name;
            this.OutputEncoding = encoding;
            this.Content = System.IO.File.ReadAllText(filename, OutputEncoding);
            this.Type = templateType;
            ParseTemplateType(templateType);
        }

        /// <summary>
        /// 用字符串构造模板
        /// </summary>
        /// <param name="name"></param>
        /// <param name="content"></param>
        /// <param name="templateType"></param>
        public Template(string name, string content, Type templateType)
        {
            this.Name = name;
            this.Content = content;
            this.Type = templateType;
            this.OutputEncoding = Encoding.Default;
            ParseTemplateType(templateType);
        }
        /// <summary>
        /// 解析模板类
        /// </summary>
        /// <param name="t"></param>
        private void ParseTemplateType(Type t)
        {
            if (t == null) return;
            foreach (var member in t.GetMembers())
            {
                var attributes = member.GetCustomAttributes(typeof(MacroAttribute), false);
                if (attributes.Length == 1)
                {
                    var attribute = attributes[0] as MacroAttribute;
                    var macro = new Macro(member, attribute);
                    if (Content.Contains(macro.FullName))
                    {   //只有模板中用到的宏才会被加载
                        Macros.Add(macro);
                    }
                }
            }
        }

        public string ReplaceToText(object instance)
        {
            if (instance.GetType() != this.Type)
            {
                throw new Exception("传入实例的类型与模板类型不一致，传入类型：" +
                    instance.GetType() + "，模板类型：" + this.Type);
            }
            string ret = Content;
            var buffer = new StringBuilder(128 * 1024);
            foreach (var macro in Macros)
            {
                buffer.Clear();
                macro.GetValue(instance, buffer);
                ret = ret.Replace(macro.FullName, buffer.ToString().Trim());
            }
            return ret;
        }

        public void ReplaceToFile(object instance, string filename)
        {
            string text = ReplaceToText(instance);
            try
            {
                File.WriteAllText(filename, text, OutputEncoding);
            }
            catch (DirectoryNotFoundException)
            {   //如果目录不存在则创建
                var dir = Path.GetDirectoryName(Path.GetFullPath(filename));
                if (!Directory.Exists(dir)) Directory.CreateDirectory(dir);
                File.WriteAllText(filename, text, OutputEncoding);
            }
        }
    }
}
